
package com.probiz.estore.webapp.filter;

import java.io.IOException;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.FilterChain;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.sf.navigator.menu.MenuComponent;
import net.sf.navigator.menu.MenuRepository;

import org.springframework.web.filter.OncePerRequestFilter;

import com.probiz.estore.Constants;
import com.probiz.estore.common.helper.ConfigUtil;
import com.probiz.estore.common.helper.MenuHelper;
import com.probiz.estore.common.model.system.AppUser;
import com.probiz.estore.common.model.system.SystemVersion;
import com.probiz.estore.system.service.SystemVersionManager;
import com.probiz.estore.webapp.util.RequestContext;
import com.probiz.estore.webapp.util.RequestUtil;
import com.probiz.estore.webapp.util.ResponseContext;

/**
 * 主要是设置基于Request的上下文环境，以及设置菜单上下文环境等。
 */
public class ActionFilter extends OncePerRequestFilter {

	private ServletContext	context;

	private boolean			isFront = false;
	
	private boolean         hasInitCtxPath = false;
	
	public static final String PARAM_GET_VERSION = "_query_version_info";

	public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
		//-------------------------------【1】设置过期时间---------------------------
//		Calendar now = Calendar.getInstance();
//		Calendar outDate = Calendar.getInstance();
//		outDate.set(2012, 4, 24, 11, 30); //年，月，日，时，分。  注意1月份是0。
//		boolean isOutDate =  outDate.compareTo(now) <= 0;
//		if(isOutDate){
//			response.sendError(200 + 206);
//			return;
//		}
		
		//-------------------------------【2】设置线程request\response变量---------------------------
		RequestContext.setCurrentHttpRequest(request);
		ResponseContext.setCurrentHttpResponse(response);
		
		//-------------------------------【3】重写会话cookie--------------------------------
		if(isFront && request.getSession().isNew()){
			//重写会话cookie。加上过期时间（半个小时），避免ie6打开新窗口不能获得对应session。
			RequestUtil.setCookie(response, "JSESSIONID", request.getSession().getId(), request.getContextPath(),30*60);
		}
		
		//-------------------------------【4】设置UID cookie，标识登录状态--------------------------------
		RequestUtil.setUserIdCookie(response, RequestContext.getCurrentUserId(), (request).getContextPath()); 
		AppUser currentUser=RequestContext.getCurrentUser();
		if (null != currentUser) {
			//每次更新UID cookie给页面，页面据此判断是否登录
			RequestUtil.setUserNameCookie(response, currentUser.getUsername(), (request).getContextPath());
		}
		
		//-------------------------------【5】在request中设置真正的访问URL属性--------------------------------
		String requestUrl = RequestUtil.getFullRequestUrl(request).toString();
        request.setAttribute(Constants.PRE_URL, requestUrl); 
        
        //-------------------------------【6】在context中设置ctxPath属性--------------------------------
        if(!hasInitCtxPath){
        	ConfigUtil.getInstance().initContextPath(request.getContextPath());
        	hasInitCtxPath = true;
        }
        
        //-------------------------------【7】在request中设置当前的被选中的菜单信息属性--------------------------------
        /**
		 * target to filter the main page request only, which don't have a
		 * decorator in url
		 */
		if (!isFront && (request.getParameter("decorator") == null)) {
			// menu handling, front-end and back-end use different
			// implementations
			MenuRepository menuRepository = (MenuRepository) context.getAttribute(MenuRepository.MENU_REPOSITORY_KEY);
			List<MenuComponent> menuContext = menuRepository.getTopMenus();
			Map<String, String> selectedMenuMap = new HashMap<String, String>();
			String queryString = request.getQueryString();
			String uri = request.getRequestURI().replace(request.getContextPath(), "") + (queryString==null?"":"?"+queryString);
			for (int i=0; menuContext != null && i < menuContext.size(); i++)
			{
			    if(MenuHelper.getSelectedMenuMap(selectedMenuMap, menuContext.get(i), uri))
			    	break;
			}
			//将被选中的菜单信息保存到request中
			request.setAttribute(Constants.SELECTED_MENU_MAP, selectedMenuMap);
		}
		
		//-------------------------------【8】在前台中查询版本信息--------------------------------
		if (isFront) {
			if (request.getParameter(PARAM_GET_VERSION) != null) {
				Object ver_obj = RequestContext.getSpringBeanById("systemVersionManager");
				if (ver_obj != null) {
					SystemVersionManager v_mgr = (SystemVersionManager) ver_obj;
					SystemVersion sv = v_mgr.getSystemVersion();
					response.setHeader("reg_copyright", "domain[" + sv.getDomainName() + "] license[" + sv.getLicenseKey() + "] ver[" + sv.getSysVersion()
							+ "] ProBIZ Software");
				}
			}
		}

		long startProcessTime = System.currentTimeMillis();
		try {
			chain.doFilter(request, response);
		} finally {
			RequestContext.clearCurrentHttpRequest();
			ResponseContext.clearCurrentHttpResponse();
		}

		//-------------------------------【final】输出日志--------------------------------
		if (logger.isDebugEnabled()) {
			// NDC.pop();
			// performance info logging
			StringBuilder sb = new StringBuilder();
			sb.append("Web Request Performance Monitor - [URL: ").append(requestUrl).append("], [Process time: ");
			sb.append(System.currentTimeMillis() - startProcessTime).append(" ms].");
			logger.debug(sb.toString());
			logger.trace(RequestUtil.getRequestInfo(request));
			
		}
	}

	protected void initFilterBean() throws ServletException {
		this.isFront = RequestContext.isFront();
		context = getServletContext();
	}
}
